package com.CmJava.SpringInterface;

import com.CmJava.annotation.aop.Pointcut;
import com.CmJava.service.MyService;
import com.CmJava.service.MyServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

public interface AopBeanPostProcessor extends BeanPostProcessor {

    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    ;


    @Override
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

    default Object postProcessAfterInitialization(Object bean, String beanName, Map<Method, Class> pointCut) {
        Class<?> targetClass = bean.getClass();
        Set<Method> methods = pointCut.keySet();
        List<String> methodsName =new ArrayList<>();
        for (Method method : methods) {
            methodsName.add(method.getName());
        }

        Object proxy0 =  Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                if (method.getName().equals("toString")){
                    return "代理对象（"+bean.getClass().getSimpleName()+"）";
                }else if (!methodsName.contains(method.getName())){
                    return method.invoke(bean, args);
                }

                Object result=null;
                Class<?>[] parameterTypes =null;
                for (Method methodPointCut : methods) {
                    if(methodPointCut.getName().equals(method.getName())){
                        Class aspectClass = pointCut.get(methodPointCut);
                        Object aspect = aspectClass.newInstance();
                        for (Method advice : aspectClass.getDeclaredMethods()) {
                            if (!advice.isAnnotationPresent(Pointcut.class)) {
                                parameterTypes = advice.getParameterTypes();
                                if (parameterTypes.length==0){
                                    result=advice.invoke(aspect,args);
                                }else {
                                    result=advice.invoke(aspect,method,bean,args);
                                }
                            }
                        }

                        break;
                    }
                }
                return result;
            }
        });



        return proxy0;

    }

    ;
}
